using System;
using System.Collections.Generic;
using System.IO;
using System.IO.IsolatedStorage;
using System.Net;
using System.Runtime.Serialization;
using System.Text;
using RTMBindings.Responses;
using System.Security.Cryptography;

namespace RTMBindings
{
    public class RTMAuthBindings : RTMBindings
    {
        private const string GetFrobUrl = UriBase + "rtm.auth.getFrob&api_key={0}";

        private const string AuthenticationUrl =
            "http://www.rememberthemilk.com/services/auth/?api_key={0}&perms=delete&frob={1}";

        private const string GetTokenUrl = UriBase + "rtm.auth.getToken&api_key={0}&frob={1}";

        private const string CheckTokenUrl = UriBase + "rtm.auth.checkToken&api_key={0}&auth_token={1}";

        private RTMAuthBindings()
        {

        }

        public static void GetFrob(string apiKey, string secret, Action<RTMGetFrobResponse> callback, Action<Exception> failedCallback)
        {
            var uri = new UriBuilder(string.Format(GetFrobUrl, apiKey));
            RequestString(secret, uri, callback, failedCallback);
        }

        public static Uri Authenticate(string apiKey, string secret, RTMFrob frob)
        {
            var uri = new UriBuilder(string.Format(AuthenticationUrl, apiKey, frob.Frob));
            SignParameters(uri, secret);
            return uri.Uri;
        }

        public static void GetToken(string apiKey, string secret, RTMFrob frob, Action<RTMGetTokenResponse> callback, Action<Exception> failedCallback)
        {
            var uri = new UriBuilder(string.Format(GetTokenUrl, apiKey, frob.Frob));
            RequestString(secret, uri, callback, failedCallback);
        }

        public static void StoreToken(RTMToken token)
        {
            var bytes = Encoding.UTF8.GetBytes(token.Token);
            var protectedBytes = ProtectedData.Protect(bytes, null);

            var file = IsolatedStorageFile.GetUserStoreForApplication();
            using (var writeStream = new IsolatedStorageFileStream("tokenfile", FileMode.Create, FileAccess.Write, file))
            {
                using (var writer = new StreamWriter(writeStream).BaseStream)
                {
                    writer.Write(protectedBytes, 0, protectedBytes.Length);
                }
            }
        }

        public static RTMToken RetrieveToken()
        {
            var file = IsolatedStorageFile.GetUserStoreForApplication();
            try
            {
                byte[] protectedBytes;
                if (!file.FileExists("tokenfile"))
                    return null;
                using (var readStream = new IsolatedStorageFileStream("tokenfile", FileMode.Open, file))
                {
                    using (var reader = new StreamReader(readStream).BaseStream)
                    {
                        protectedBytes = new byte[reader.Length];
                        reader.Read(protectedBytes, 0, protectedBytes.Length);
                    }
                }

                var bytes = ProtectedData.Unprotect(protectedBytes, null);
                var tok = Encoding.UTF8.GetString(bytes, 0, bytes.Length);
                return new RTMToken {Token = tok};
            }
            catch (FileNotFoundException)
            {
                return null;
            }
        }

        public static void CheckToken(string apiKey, string secret, RTMToken token, Action<RTMGetTokenResponse> callback, Action<Exception> failedCallback)
        {
            var uri = new UriBuilder(string.Format(CheckTokenUrl, apiKey, token.Token));
            RequestString(secret, uri, callback, failedCallback);
        }
    }
}